//
//  Controller.m
//  Broadcaster
//
//  Created by Blagovest Dachev on 2/1/09.
//  Copyright 2009 __MyCompanyName__. All rights reserved.
//
#import <string>

#import "Controller.h"
#import "Keychain.h"


@implementation Controller

-(void)dealloc
{
    [statusItem release];
	[menuIconOn release];
	[menuIconOff release];
	[prefs release];
	[container autorelease];
	[remoteControlBehavior autorelease];
	[super dealloc];
}

- (void)awakeFromNib
{	
    prefs = [[NSUserDefaults standardUserDefaults] retain];

	/* Create status icon */
    NSBundle * bundle   = [NSBundle bundleForClass:[self class]];
    NSString * path_on  = [bundle pathForResource:@"status_on"  ofType:@"png"];
    NSString * path_off = [bundle pathForResource:@"status_off" ofType:@"png"];

    menuIconOn  = [[NSImage alloc] initWithContentsOfFile:path_on];
    menuIconOff = [[NSImage alloc] initWithContentsOfFile:path_off];
    statusItem  = [[[NSStatusBar systemStatusBar] statusItemWithLength:NSVariableStatusItemLength] retain];
	
	[statusItem setTitle:[NSString stringWithString:@""]];
	[statusItem setImage:menuIconOff];
	[statusItem setMenu:theMenu];
	[statusItem setHighlightMode:YES];
	
	[theMenu setAutoenablesItems:NO];
	[connectItem setEnabled: NO];
	
	/* Enable connect button */
	NSString *pass = [Keychain getPassword];
	NSString *sJID = [prefs stringForKey:@"sJID"];
	NSString *dJID = [prefs stringForKey:@"dJID"];

	if ([sJID length] > 0 && [dJID length] > 0 && [pass length] > 0) {
		[connectItem setEnabled: YES];
	}
	
	/* Connect to XMPP */
	messanger = NULL;
	[self connect];
	[NSThread detachNewThreadSelector:@selector(checkStatus) toTarget:self withObject:self];
}

-(void)applicationWillResignActive:(NSNotification *)aNotification {
    [container stopListening: self];
}

-(IBAction)respondConnect:(id)sender
{	
	if ([[connectItem title] isEqualToString: @"Connect"]) {
		[prefs setBool:YES forKey:@"connect"];
		[self connect];
	}
	else {
		[prefs setBool:NO forKey:@"connect"];
		[self disconnect];
	}
}

-(IBAction)respondShowSettings:(id)sender
{
	NSString *pass = [Keychain getPassword];
	NSString *sJID = [prefs stringForKey:@"sJID"];
	NSString *dJID = [prefs stringForKey:@"dJID"];
	
	sJID = (sJID == nil) ? @"" : [NSString stringWithString:sJID];
	dJID = (dJID == nil) ? @"" : [NSString stringWithString:dJID];
	
	[sJIDField setStringValue: sJID];
	[dJIDField setStringValue: dJID];
	[passwordField setStringValue: pass];
	
	[statusField setStringValue: @""];
	
	[NSApp activateIgnoringOtherApps:YES];
	[settings makeKeyAndOrderFront:nil];
}

-(IBAction)respondShowAbout:(id)sender
{	
	[NSApp activateIgnoringOtherApps:YES];
	[about makeKeyAndOrderFront:nil];
}

-(IBAction)respondQuit:(id)sender
{
    [NSApp terminate:self];
}

-(IBAction)respondSave:(id)sender
{
	BOOL success = YES;
	
	[statusField setStringValue: @""];
	[saveButton setEnabled: NO];

	NSString * sJID = [sJIDField stringValue];
	NSString * dJID = [dJIDField stringValue];
	NSString * pass = [passwordField stringValue];
	
	/* Check for empty fields */
	if ([sJID length] == 0 || [dJID length] == 0 || [pass length] == 0) {
		[statusField setStringValue: @"Some of the fields are empty. Please try again."];
		success = NO;
	}
	
	/* Try to connect and authenticate */
	string * user_test = new string([sJID UTF8String]);
	string * pass_test = new string([pass UTF8String]);
	[statusField setStringValue: @"Connecting..."];
	if (Messanger::test(user_test, pass_test) == false) {
		[statusField setStringValue: @"Unable to connect. Plesae try again."];
		success = NO;
	}
	delete user_test;
	delete pass_test;
	
	/* Save new settings */
	if (success == YES) {
		[prefs setObject:[NSString stringWithString:sJID] forKey:@"sJID"];
		[prefs setObject:[NSString stringWithString:dJID] forKey:@"dJID"];

		if ([Keychain checkForExistanceOfKeychain] > 0) {
			[Keychain modifyKeychainItem:pass];
		} else {
			[Keychain addKeychainItem:pass];
		}
	
		[statusField setStringValue: @"OK."];
		[connectItem setEnabled: YES];
		
		[self connect];
	}

	[saveButton setEnabled: YES];
}

/* delegate method for the MultiClickRemoteBehavior */
- (void) remoteButton: (RemoteControlEventIdentifier)buttonIdentifier pressedDown: (BOOL) pressedDown clickCount: (unsigned int)clickCount
{
	if ([self isConnected] == NO || [self isAuthenticated] == NO || [self isOnline] == NO) {
		return;	
	}
	
	NSString* buttonName=nil;
	NSString* pressed=@"";
	
	if (pressedDown) pressed = @"pressed"; else pressed = @"released";
	
	switch(buttonIdentifier) {
		case kRemoteButtonPlus:
			buttonName = @"up";			
			break;
		case kRemoteButtonMinus:
			buttonName = @"down";
			break;			
		case kRemoteButtonMenu:
			buttonName = @"menu";
			break;			
		case kRemoteButtonPlay:
			buttonName = @"play";
			break;			
		case kRemoteButtonRight:	
			buttonName = @"right";
			break;			
		case kRemoteButtonLeft:
			buttonName = @"left";
			break;
		case kRemoteButtonRight_Hold:
			buttonName = @"right";
			pressed = @"holding";
			break;	
		case kRemoteButtonLeft_Hold:
			buttonName = @"left";
			pressed = @"holding";
			break;			
		case kRemoteButtonPlus_Hold:
			buttonName = @"up";
			pressed = @"holding";
			break;				
		case kRemoteButtonMinus_Hold:
			buttonName = @"down";
			pressed = @"holding";
			break;
		case kRemoteButtonPlay_Hold:
			buttonName = @"play";
			pressed = @"holding";
			break;			
		case kRemoteButtonMenu_Hold:
			buttonName = @"menu";
			pressed = @"holding";
			break;
		/*
		case kRemoteControl_Switched:
			buttonName = @"Remote Control Switched";
			break;
		*/
		default:
			NSLog(@"Unmapped event for button %d", buttonIdentifier); 
			break;
	}
	
	if (buttonName == nil) {
		return;
	}
	
	NSString * msg = [NSString stringWithFormat:@"%@,%@", buttonName, pressed];
	string cppmsg([msg UTF8String]);
	messanger->send(cppmsg);
}

-(void)connect
{
	[self disconnect];
	
	BOOL connect = [prefs boolForKey:@"connect"];
	
	if (connect != YES) {
		return;
	}

	/* Get connection settings */
	NSString *pass = [Keychain getPassword];
	NSString *sJID = [prefs stringForKey:@"sJID"];
	NSString *dJID = [prefs stringForKey:@"dJID"];
	
	sJID = (sJID == nil) ? @"" : [NSString stringWithString:sJID];
	dJID = (dJID == nil) ? @"" : [NSString stringWithString:dJID];
	
	string * cpp_sJID = new string([sJID UTF8String]);
	string * cpp_dJID = new string([dJID UTF8String]);
	string * cpp_pass = new string([pass UTF8String]);

	/* Establish connection */
	if (!cpp_sJID->empty() && !cpp_dJID->empty() && !cpp_pass->empty()) {
		[connectItem setEnabled: YES];
	
		messanger = new Messanger(cpp_sJID, cpp_pass, cpp_dJID);
		messanger->connect();
	}
	
	delete cpp_sJID;
	delete cpp_dJID;
	delete cpp_pass;
	
	/* Create remote control wrapper instance */
	[self start];
}

-(void)disconnect
{
	if (messanger != NULL) {
		messanger->disconnect();
		delete messanger;
		messanger = NULL;
	}
	
	[self stop];
}

-(void)start
{
	if (container == nil) {
		remoteControlBehavior = [[MultiClickRemoteBehavior alloc] init];
		[remoteControlBehavior setDelegate: self];
		container = [[RemoteControlContainer alloc] initWithDelegate: remoteControlBehavior];
		[container instantiateAndAddRemoteControlDeviceWithClass: [AppleRemote class]];
		//[container instantiateAndAddRemoteControlDeviceWithClass: [KeyspanFrontRowControl class]];
		//[container instantiateAndAddRemoteControlDeviceWithClass: [GlobalKeyboardDevice class]];
	}
	
	NSDictionary* defaultValues = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithBool: YES], @"remoteControlWrapperFixSecureEventInputBug", nil];
    [prefs registerDefaults:defaultValues];
	
	[container startListening: self];
}

-(void)stop
{
	if (container != nil) {
		[container stopListening: self];
	}
	
	//[remoteControlBehavior release];
	//[container release];
	//container = nil;
}

-(BOOL)isOnline
{
    Boolean success;
    BOOL okay;
    SCNetworkConnectionFlags status;

    success = SCNetworkCheckReachabilityByName("www.apple.com", &status);

    okay = success && (status & kSCNetworkFlagsReachable) && !(status & kSCNetworkFlagsConnectionRequired);

    if (!okay) {
        success = SCNetworkCheckReachabilityByName("www.w3.org", &status);

        okay = success && (status & kSCNetworkFlagsReachable) && !(status & kSCNetworkFlagsConnectionRequired);
    }

    return okay;
}

-(BOOL)isConnected
{
    return messanger != NULL && messanger->isConnected() ;
}

-(BOOL)isAuthenticated
{
    return messanger->isAuthenticated();
}

-(BOOL)isXMPPReady
{
    return [self isConnected] && [self isAuthenticated];
}

-(void)checkStatus
{
	int counter = 0;
	NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

	while(1) {
		if ([self isXMPPReady] == YES) {
			[statusItem setImage:menuIconOn];
			[connectItem setTitle: @"Disconnect"];
			
			if ([container isListeningToRemote] == NO) {
			    NSLog(@"----------------");
				[self start];
			}
		}
		else {
			[statusItem setImage:menuIconOff];
			[connectItem setTitle: @"Connect"];
			
			if ([container isListeningToRemote] == YES) {
				[self stop];
			}
		}
		
		[NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:1]];
		
		counter++;
		
		BOOL connect = [prefs boolForKey:@"connect"];
		if (counter == 15) {
			counter = 0;
			
			if ([self isOnline] == NO) {
				[self stop];
				[self disconnect];
			}
			
			if ([self isConnected] == NO || [self isAuthenticated] == NO) {
				if ([self isOnline] == YES && connect == YES) {
					[self disconnect];
					[self connect];
				}
			}
		}
	}

	[pool release];
}

@end


